
#ifndef __GARBAGE_MANAGER_H__
#define __GARBAGE_MANAGER_H__

#include "GarbageObject.h"
#include <vector>
#include <unordered_set>
#include <unordered_map>

/*
    垃圾管理器

    提供简单的垃圾管理，采用引用计数+标记清除的方式
        若引用计数为0则会视为是垃圾，在清理阶段会被直接清除
        清理前会从根节点出发对所有引用中的对象做标记，没有被标记到的会被视作垃圾，清理阶段会被清除
注意点：
    1. 需要直接或间接的继承GarbageObject
    2. 如果不想对象被当做垃圾清理掉，那就调用Retain/Release声明使用中
    3. 若需要被其他对象引用Retain/Release需要加上被哪个对象引用
        - value->Retain(this)   被this引用
        - value->Release(this)  释放被this的引用
    4. 不支持多线程
*/

class GarbageManager : public GarbageObject
{
    Single(GarbageManager);
    friend class GarbageObject;

public:

    // 立即执行一次垃圾清理
    // force:强制现在清理，否则将延迟到下次垃圾回收器更新时清理
    void Clear(bool force = false);

    // 垃圾回收器更新
    void update(float dt);

    // 获取垃圾占用内存
    size_t GetGarbageCount() const;

    // 获取垃圾总数
    size_t GetGarbageMemory() const;

    // 获取当前new的对象数
    size_t GetNowNewObjectCount() const;

    // 获取当前new的对象占用内存
    size_t GetNowNewObjectMemory() const;

private:
    // 添加一个垃圾
    void Push(GarbageObject* obj, bool markPush = false);

    // new一个对象时被obj调用
    void onNewObj(GarbageObject* obj);

    // delete一个对象时被obj调用
    void onRemoveObj(GarbageObject* obj);


private:
    // 标记处理
    void processMark();

    // 处理实际删除操作
    void processRealDelete();

private:
    // 检查垃圾总数
    bool CheckAutoGcGarbageCount() const;

    // 检查垃圾内存
    bool CheckAutoGcGarbageMemory() const;

    // 检查自动回收间隔
    bool CheckAutoGcTimer(float dt);

    // 检查调用次数
    bool CheckAutoGcCallCount();

    // 释放减少引用
	virtual void Release(GarbageObject* target = nullptr);
	
    // 保留增加引用
	virtual void Retain(GarbageObject* target = nullptr);

public:
    std::vector<GarbageObject*> list_;      // 垃圾列表
    size_t totalSize_;                      // 垃圾占用内存总数
    bool isNeedClear_;                      // 需要清理

    size_t autoGcGarbageCount_;             // 自动清理垃圾数量占用
    size_t autoGcGarbageMemory_;            // 自动清理垃圾内存占用
    float autoGcInterval_;                  // 自动清理间隔
    size_t autoGcCount_;                    // 自动清理次数

    float autoGcIntervalVal_;               // 自动清理间隔累计值
    size_t autoGcCountVal_;                 // 自动清理次数累计值

    size_t nowNewCount_;                    // 当前new出来的对象数量
    size_t nowNewMemory_;                   // 当前new出来的对象大小

    std::unordered_set<GarbageObject*> objects_;            // 所有申请的对象备案
    std::unordered_map<GarbageObject*, int> rootRefTable_;  // 根引用表
};

#endif
